from __future__ import with_statement

from google.appengine.ext import blobstore
from google.appengine.ext import deferred
from google.appengine.api import mail
from google.appengine.ext import db

import logging
import string 
import os.path
import cachedstore

from models import *

class UpdatePeriodical():    
    
    def updateDeferred(self, key, filename, filesizeKB, last_update):
        logging.debug("Queueing periodical %s update" % filename)
        deferred.defer(self.update, key, filename, filesizeKB, last_update)
    
    def update(self, key, filename, filesizeKB, last_update):
        periodical_name = os.path.splitext(filename)[0]
        keyName = string.replace(filename.lower(),'.','_')
        
        blob_key = blobstore.BlobKey(key)
                
        #update existing periodical
        periodical = Periodical.get_by_key_name(keyName)        
        if periodical:            
            logging.debug("Updating periodical %s" % keyName)
            old_blobinfo = periodical.blobfile            
            periodical.blobfile = blob_key
            periodical.last_update = last_update
            periodical.filesizeKB = filesizeKB
            periodical.put()        
            
            if old_blobinfo:
                # delete old blob                
                cachedstore.delete(old_blobinfo.key())            
            
        else:
            # create a new one
            logging.debug("Creating periodical %s", keyName)
            periodical = Periodical.get_or_insert(key_name = keyName, 
                                                  name=periodical_name,
                                                  filename = filename,
                                                  last_update = last_update,
                                                  filesizeKB = filesizeKB,
                                                  blobfile = blob_key)        
        
        # clear cache
        Periodical.clearCache()
        
        # process subscriptions
        deferred.defer(self.send, keyName)
        
    def sendDeferred(self, keyName):
        logging.debug("Queueing periodical %s send" % keyName)
        deferred.defer(self.send, keyName)
        
    def send(self, keyName): 
                
        FETCHLIMIT = 100
               
        periodical = Periodical.get_by_key_name(keyName)   
        
        # skip for no periodical or non-existing file
        if not periodical or periodical.blobfile is None:
            return
        
        logging.debug("Processing periodical %s subscriptions" % keyName)
        
        query = Subscription.all()
        query.ancestor(periodical)
        query.filter("send_next <= ", datetime.now()) # due subscriptions 
        
        subscriptions = query.fetch(FETCHLIMIT)
        
        if not subscriptions or len(subscriptions) < 1:
            logging.debug("Nothing to process for %s." % keyName)
            return 
        
        subscriptionsToUpdate = []        
        emails = [] 
    
        for subscription in subscriptions:
            # skip if already sent
            if subscription.send_last is not None and subscription.send_last > periodical.last_update:
                continue            
            
            # add email
            emails.append(subscription.user_settings.email)
            
            # update subscription
            subscription.send_last = datetime.now()
            subscription.setNextSend()
            subscriptionsToUpdate.append(subscription)
            
        if len(emails) > 0:          
            # send emails and save 
            self.sendMails(periodical, subscriptionsToUpdate, emails)
            #db.run_in_transaction(self.sendMails, periodical, subscriptionsToUpdate, emails)
                    
            if len(subscriptions) == FETCHLIMIT:   
                # there might be still something to send
                deferred.defer(self.send, keyName)
        
            
    def sendMails(self, periodical, subscriptionsToUpdate, emails):        
        logging.debug("Running periodical %s subscription transaction for %i emails" % (periodical.key().name(), len(emails)))        
        blobinfo = periodical.blobfile
        
        if not blobinfo:
            return
                
        filecontent = cachedstore.load(blobinfo.key())
        
        info = "kindly.cz subscription - %s" % blobinfo.filename
        emailString = ';'.join(emails)
        
        logging.debug("Sending to emails %s" % emailString)        
         
        mail.send_mail(sender="subscriptions@kindly.cz",
                       to="recipients@kindly.cz",
                       bcc=emailString,
                       subject=info,
                       body=info,
                       attachments=[(blobinfo.filename, filecontent)])
        
        # save subscriptions
        db.put(subscriptionsToUpdate)